package net.qiqbframework.eventhandling;


import net.qiqbframework.messaging.GenericMessage;
import net.qiqbframework.messaging.Message;
import net.qiqbframework.messaging.MetaData;

import java.time.Instant;
import java.util.Map;
import java.util.function.Supplier;


public class GenericDomainEventMessage<T> extends GenericEventMessage<T> implements DomainEventMessage<T> {

    private final String type;
    private final String aggregateIdentifier;
    private final long sequenceNumber;


    public GenericDomainEventMessage(String type, String aggregateIdentifier, long sequenceNumber, T payload) {
        this(type, aggregateIdentifier, sequenceNumber, payload, MetaData.emptyInstance());
    }

    public GenericDomainEventMessage(String type, String aggregateIdentifier, long sequenceNumber, T payload,
                                     Map<String, ?> metaData) {
        this(type, aggregateIdentifier, sequenceNumber, new GenericMessage<>(payload, metaData), clock.instant());
    }

    public GenericDomainEventMessage(String type, String aggregateIdentifier, long sequenceNumber, T payload,
                                     Map<String, ?> metaData, String messageIdentifier, Instant timestamp) {
        this(type, aggregateIdentifier, sequenceNumber, new GenericMessage<>(messageIdentifier, payload, metaData),
                timestamp);
    }


    public GenericDomainEventMessage(String type, String aggregateIdentifier, long sequenceNumber, Message<T> delegate,
                                     Supplier<Instant> timestamp) {
        super(delegate, timestamp);
        this.type = type;
        this.aggregateIdentifier = aggregateIdentifier;
        this.sequenceNumber = sequenceNumber;
    }


    public GenericDomainEventMessage(String type, String aggregateIdentifier, long sequenceNumber,
                                     Message<T> delegate, Instant timestamp) {
        super(delegate, timestamp);
        this.type = type;
        this.aggregateIdentifier = aggregateIdentifier;
        this.sequenceNumber = sequenceNumber;
    }

    @Override
    public String getAggregateType() {
        return type;
    }

    @Override
    public String getAggregateIdentifier() {
        return aggregateIdentifier;
    }

    @Override
    public long getSequenceNumber() {
        return sequenceNumber;
    }


    @Override
    protected void describeTo(StringBuilder stringBuilder) {
        super.describeTo(stringBuilder);
        stringBuilder.append('\'').append(", aggregateType='")
                .append(getAggregateType()).append('\'')
                .append(", aggregateIdentifier='")
                .append(getAggregateIdentifier()).append('\'')
                .append(", sequenceNumber=")
                .append(getSequenceNumber());
    }

    @Override
    protected String describeType() {
        return "GenericDomainEventMessage";
    }
}
